#include "pcap.hpp"
#include "MDDP.hpp"
#include <unordered_map>
#include <map>
#include "MDDPParser.hpp"
#include "Market.hpp"
#include "TradingPlatform.hpp"

using namespace std;

StockMarket::Market market;

struct UdpStream
{
    uint16_t src, src_port, dst, dst_port;
    UdpStream() : src(0), src_port(0), dst(0), dst_port(0) {}
};
struct UdpStreamHash
{
    std::size_t operator()(const UdpStream &stream) const
    {
        // 将各个字段进行异或操作生成哈希值
        std::size_t h1 = std::hash<uint16_t>()(stream.src);
        std::size_t h2 = std::hash<uint16_t>()(stream.src_port);
        std::size_t h3 = std::hash<uint16_t>()(stream.dst);
        std::size_t h4 = std::hash<uint16_t>()(stream.dst_port);
        return h1 ^ h2 ^ h3 ^ h4;
    }
};

struct UdpStreamEqual
{
    bool operator()(const UdpStream &lhs, const UdpStream &rhs) const
    {
        // 判断各个字段是否相等
        return (lhs.src == rhs.src) && (lhs.src_port == rhs.src_port) && (lhs.dst == rhs.dst) && (lhs.dst_port == rhs.dst_port);
    }
};

unordered_map<UdpStream, vector<vector<uint8_t>>, UdpStreamHash, UdpStreamEqual> udp_map;

void parseMddp(uint8_t *packet, const size_t len_packet)
{
    MddpProtocolHeader *mddp_header = (MddpProtocolHeader *)(packet);
    // mddp_header->ntoh();
    if (mddp_header->protocol != 0xff || mddp_header->version != 0x01)
    {
        // cout << "protocol error" << endl;
    }
    else
    {
        {
            // 最后减 4 是减去checksum的长度
            uint32_t _checksum = MddpProtocolHeader::adler32((uint8_t *)mddp_header,
                                                             len_packet -
                                                                 sizeof(Ipv4PacketHeader) - sizeof(UdpPacketHeader) - 4);

            uint32_t checksum = __builtin_bswap32(*(uint32_t *)(packet + len_packet - 4));
            if (checksum != _checksum)
            {
                printf("MDDP checksum error\n");
                return;
            }
        }
        if (mddp_header->flag.msg_header)
        {
            printf("msg_header: %d\n", mddp_header->flag.msg_header);
        }
        else
        {
            uint8_t *data = (uint8_t *)mddp_header + mddp_header->header_size * 4;
            int ret = MDDPMessageParser::parse(data, len_packet -
                                                         sizeof(Ipv4PacketHeader) -
                                                         sizeof(UdpPacketHeader) -
                                                         mddp_header->header_size * 4 -
                                                         4); // 最后再减去4是减去checksum的长度
            if (ret < 0)
            {
                printf("MDDP parse error\n");
            }
        }
    }
}

void parseMddp(std::vector<uint8_t> &packet)
{
    parseMddp(packet.data(), packet.size());
}

long long no_error = 0, error = 0;

int main(int argc, char **argv)
{
    market.createETF("/home/wang/Documents/github/internship/mddp/申购赎回清单.txt");
    TradingPlatform platform;
    platform.addETF(market.getETF(159915));
    std::thread t(&TradingPlatform::run, &platform);

    {
        const std::string file("/home/wang/Documents/github/internship/tcp_binary.pcap");
        PcapPaser paser(file);
        paser.open();

        while (!paser.isEOF())
        {
            std::vector<uint8_t> ip_packet = paser.getIP();
            if (ip_packet.empty())
                continue;
            Ipv4PacketHeader *ip_header = (Ipv4PacketHeader *)ip_packet.data();
            ip_header->ntoh();

            TcpPacketHeader *tcp_header = (TcpPacketHeader *)(ip_packet.data() + sizeof(Ipv4PacketHeader));
            tcp_header->ntoh();

            // parseMddp((uint8_t*)tcp_header + sizeof(TcpPacketHeader), ip_packet.size() - sizeof(Ipv4PacketHeader) - sizeof(TcpPacketHeader));
            {
                uint8_t *data = (uint8_t *)tcp_header + sizeof(TcpPacketHeader);
                int ret = MDDPMessageParser::parse(data, ip_packet.size() - sizeof(Ipv4PacketHeader) - sizeof(TcpPacketHeader));
            }
        }
        platform.stop();
    }

    t.join();

    platform.log("/home/wang/Documents/github/internship/mddp/log.csv");

    return 0;
}
